package com.koi.dict.aspect;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.koi.common.anno.KoiDict;
import com.koi.common.anno.KoiDictClass;
import com.koi.common.constants.KoiCacheConstants;
import com.koi.common.redis.RedisUtil;
import com.koi.pojo.system.SysDictData;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.Field;
import java.util.*;

/**
 * @author ･ᴗ･
 * @description [KoiDictAspect]
 */
@Aspect
@Order(4)
@Component
@Slf4j
public class KoiDictAspect {

    private Map<String, String> dictMap = new HashMap<>();

    @Resource
    private RedisUtil redisUtil;

    @Pointcut("@annotation(com.koi.common.anno.KoiDictClass)")
    public void logPointCut() {
    }

    /**
     * @description [翻译数据]
     * 需要处理的数据类型：
     * 1、分页数据R<IPage<T>>
     * 2、普通列表R<List<T>>
     * 3、普通数据R<T>
     * @author ･ᴗ･
     */
    @Around("@annotation(koiDictClass)")
    public Object koiTypeDictTranslation(final ProceedingJoinPoint proceedingJoinPoint, KoiDictClass koiDictClass) throws Throwable {
        Object proceed = proceedingJoinPoint.proceed();
        if (ObjectUtils.isEmpty(proceed)) {
            return proceed;
        }
        if (proceed instanceof List) {
            // 数据字典翻译
            List<Object> list = (List<Object>) proceed;
            koiDictTranslate(list);
            return list;
        } else if (proceed instanceof Page) {
            // Page 类型处理逻辑
            IPage page = (IPage) proceed;
            List records = page.getRecords();
            // 数据字典翻译
            koiDictTranslate(records);
            page.setRecords(records);
            // 返回修改后的分页对象
            return page;
        } else {
            // 其他类型处理逻辑或错误处理
            return proceed;
        }
    }

    /**
     * @description [获取不同类型返回结果数据进行翻译]
     * @author ･ᴗ･
     */
    private void koiDictTranslate(Object resultData) {
        Object objectData;
        // 检查输入的result是否是List或者ArrayList的实例
        if (resultData instanceof List) {
            // 如果是列表，则获取第一个元素
            List koiList = ((List) resultData);
            // 如果列表为空，则直接返回原始结果
            if (koiList.isEmpty()) {
                return;
            }
            // 获取集合的第一条数据
            objectData = koiList.get(0);
        } else {
            // 否则直接使用result对象
            objectData = resultData;
        }
        // 获取数据字典key 和 实体类字段名称
        List<KoiDictModel> dictModelList = getKoiDict(objectData.getClass());
        // dictModelList.forEach(System.out::println);
        // KoiDictModel(dictKey=sys_user_sex, dictValue=sex)
        // 如果没有字典映射，则直接返回原始结果
        if (dictModelList.isEmpty()) {
            return;
        }

        // 获取所有的字典数据
        List<SysDictData> dictDataList = listDictCache(dictModelList);

        // 如果字典数据是空则直接返回
        if (CollectionUtils.isEmpty(dictDataList)) {
            return;
        }
        // 将字典值转换成map形式
        for (SysDictData dictData : dictDataList) {
            dictMap.put(dictData.getDictType() + "_" + dictData.getDictValue(), dictData.getDictLabel());
        }
        // 根据对象类型，为返回数据的每一个对象赋予字典值
        if (resultData instanceof List) {
            for (Object entity : (List) resultData) {
                assignDictValue(entity, dictModelList, dictMap);
            }
        } else {
            assignDictValue(resultData, dictModelList, dictMap);
        }
    }


    /**
     * @description [获取字典数据缓存]
     * @author ･ᴗ･
     */
    private List<SysDictData> listDictCache(List<KoiDictModel> dictModelList) {
        // 测试代码
        // List<SysDictData> dictList = new ArrayList<>();
        // SysDictData dict1 = new SysDictData();
        // dict1.setDictType("sys_user_sex");
        // dict1.setDictLabel("男");
        // dict1.setDictValue("1");
        // dictList.add(dict1);
        // SysDictData dict2 = new SysDictData();
        // dict2.setDictType("sys_user_sex");
        // dict2.setDictLabel("女");
        // dict2.setDictValue("2");
        // dictList.add(dict2);
        //
        // SysDictData dict3 = new SysDictData();
        // dict3.setDictType("sys_switch_status");
        // dict3.setDictLabel("启用");
        // dict3.setDictValue("0");
        // dictList.add(dict3);
        //
        // SysDictData dict4 = new SysDictData();
        // dict4.setDictType("sys_switch_status");
        // dict4.setDictLabel("停用");
        // dict4.setDictValue("1");
        // dictList.add(dict4);

        List<SysDictData> dictDataList = new ArrayList<>();
        List<String> dictKeyList = getDictKey(dictModelList);
        for (String dictKey : dictKeyList) {
            Boolean hasKey = redisUtil.hasKey(KoiCacheConstants.DICT_REDIS_KEY + dictKey);
            if(hasKey) {
                List<SysDictData> dictDataKeyList = redisUtil.getKey(KoiCacheConstants.DICT_REDIS_KEY + dictKey);
                dictDataList.addAll(dictDataKeyList);
            }
        }
        return dictDataList;
    }


    /**
     * @param entity        返回List集合数据循环出来的实体类对象，转换字典的核心代码
     * @param dictModelList KoiDictModel(dictKey=sys_user_sex, dictValue=sex) 获取实体类的@KoiDict注解值
     * @param dictMap       所有字典数据缓存
     */
    public void assignDictValue(Object entity, List<KoiDictModel> dictModelList, Map<String, String> dictMap) {
        try {
            // 遍历每个KoiDictModel对象
            for (KoiDictModel dictModel : dictModelList) {
                String dictKey = dictModel.getDictKey(); // 获取字典类型
                String fieldName = dictModel.getDictValue(); // 获取需要赋值的字段名
                Class<?> classData = entity.getClass(); // 获取实体类的类
                Field fieldData = classData.getDeclaredField(fieldName); // 获取需要赋值的字段
                fieldData.setAccessible(true); // 设置字段可访问性
                Object originalValue = fieldData.get(entity); // 获取字段的原始值
                if (ObjectUtils.isNotEmpty(originalValue)) {
                    // 如果原始值不为空，则将字典值赋给字段
                    String dictValue = dictMap.getOrDefault(dictKey + "_" + originalValue, originalValue.toString());
                    fieldData.set(entity, dictValue);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 获取实体中所有需要翻译的dictKey，返回需要翻译的dictKey列表
     */
    private List<String> getDictKey(List<KoiDictModel> koiDictBos) {
        // 创建一个字符串列表用于存储dictKey
        List<String> dictKeyList = new ArrayList<>();
        // 如果传入的KoiDictBo为空，则直接返回空列表
        if (CollectionUtils.isEmpty(koiDictBos)) {
            return dictKeyList;
        }
        for (KoiDictModel dictBo : koiDictBos) {
            // 将每个KoiDictBo对象的key添加到列表中
            dictKeyList.add(dictBo.getDictKey());
        }
        return dictKeyList;
    }

    /**
     * 获取实体类中配置的dictKey 和 对应的字段名称
     */
    private List<KoiDictModel> getKoiDict(Class classData) {
        Field[] fields = classData.getDeclaredFields(); // 获取类classData中声明的所有字段
        List<KoiDictModel> list = new ArrayList<>(); // 创建一个KoiDictBo列表
        KoiDictModel koiDictBo;
        KoiDict koiDict;
        for (Field field : fields) {
            if (field.isAnnotationPresent(KoiDict.class)) { // 检查字段是否带有KoiDict注解
                koiDict = field.getAnnotation(KoiDict.class); // 获取KoiDict注解
                koiDictBo = new KoiDictModel(koiDict.dictKey(), field.getName()); // 创建koiDictBo对象，存储dictKey和字段名
                list.add(koiDictBo);
            }
        }
        // 返回包含配置的dictKey和对应字段内容的列表
        return list;
    }

}



